package com.nova.android.tvlauncher.ui.view

import android.animation.ArgbEvaluator
import android.animation.ValueAnimator
import android.content.Context
import android.graphics.Color
import android.graphics.Rect
import android.graphics.drawable.GradientDrawable
import android.util.AttributeSet
import android.view.LayoutInflater
import android.view.View
import android.view.animation.DecelerateInterpolator
import android.widget.FrameLayout
import androidx.core.content.withStyledAttributes
import com.nova.android.tvlauncher.R
import com.nova.android.tvlauncher.databinding.FocusNotifyViewBinding

/**
 * 自定义视图，支持带文本的焦点通知效果。
 * 提供聚焦和非聚焦状态的背景颜色、缩放动画以及文本显示效果。
 * 不涉及图片资源，仅处理文本和背景的焦点效果。
 */
class FocusNotifyWithTextView @JvmOverloads constructor(
    context: Context,
    attrs: AttributeSet? = null,
    defStyleAttr: Int = 0
) : FrameLayout(context, attrs, defStyleAttr) {

    // 数据绑定对象，用于访问布局中的视图
    private var binding: FocusNotifyViewBinding =
        FocusNotifyViewBinding.inflate(LayoutInflater.from(context), this, true)

    // 聚焦状态的背景颜色，默认为白色
    private var focusColor: Int = Color.WHITE
    // 非聚焦状态的背景颜色，默认为透明
    private var normalColor: Int = Color.TRANSPARENT
    // 聚焦时的缩放比例，默认为 1.2
    private var scaleFactor: Float = 1.2f
    // 动画持续时间（毫秒），默认为 400
    private var animationDuration: Long = 400
    // 动画插值器，默认为减速插值器
    private var interpolator = DecelerateInterpolator()
    // 背景渐变 drawable，用于动态设置背景颜色
    private var backgroundDrawable: GradientDrawable? = null
    // 聚焦时的文本内容，默认为空
    private var focusTextContent: String = ""
    // 聚焦文本的大小（sp），默认为 14
    private var focusTextSize: Float = 14f
    // 聚焦文本的颜色，默认为白色
    private var focusTextColor: Int = Color.WHITE

    /**
     * 初始化块，读取自定义属性并设置视图初始状态。
     */
    init {
        // 从 XML 属性中读取自定义属性
        context.withStyledAttributes(attrs, R.styleable.FocusNotifyWithTextView) {
            focusColor = getColor(R.styleable.FocusNotifyWithTextView_fnwt_focus_color, Color.WHITE)
            normalColor = getColor(R.styleable.FocusNotifyWithTextView_fnwt_normal_color, Color.TRANSPARENT)
            scaleFactor = getFloat(R.styleable.FocusNotifyWithTextView_fnwt_scale_factor, 1.2f).coerceAtLeast(1.0f)
            animationDuration = getInt(R.styleable.FocusNotifyWithTextView_fnwt_animation_duration, 400).toLong()
            focusTextContent = getString(R.styleable.FocusNotifyWithTextView_fnwt_focus_text_content) ?: ""
            focusTextSize = getDimension(R.styleable.FocusNotifyWithTextView_fnwt_focus_text_size, 14f)
            focusTextColor = getColor(R.styleable.FocusNotifyWithTextView_fnwt_focus_text_color, Color.WHITE)
        }

        // 启用 FrameLayout 的焦点支持，使视图可聚焦
        isFocusable = true
        isFocusableInTouchMode = true

        // 允许子视图超出边界，以支持缩放动画
        clipChildren = false
        clipToPadding = false

        // 初始化背景、文本和焦点状态
        setupBackground()
        setupText()
        updateFocusState(isFocused, false)
    }

    /**
     * 设置背景 drawable，初始化背景形状和颜色。
     */
    private fun setupBackground() {
        backgroundDrawable = GradientDrawable().apply {
            shape = GradientDrawable.OVAL // 设置背景为椭圆形
            setColor(if (isFocused) focusColor else normalColor) // 根据焦点状态设置颜色
        }
        binding.rlBg.background = backgroundDrawable
    }

    /**
     * 设置文本属性，包括内容、大小、颜色和初始可见性。
     */
    private fun setupText() {
        binding.focusText.apply {
            text = focusTextContent // 设置文本内容
            textSize = focusTextSize / resources.displayMetrics.scaledDensity // 转换为 sp
            setTextColor(focusTextColor) // 设置文本颜色
            alpha = if (isFocused) 1.0f else 0.0f // 设置初始透明度
            visibility = if (isFocused) VISIBLE else INVISIBLE // 设置初始可见性
        }
    }

    /**
     * 焦点状态改变时调用，更新视图状态。
     *
     * @param focused 是否获得焦点
     * @param direction 焦点移动方向
     * @param previouslyFocusedRect 前一个焦点区域
     */
    override fun onFocusChanged(focused: Boolean, direction: Int, previouslyFocusedRect: Rect?) {
        super.onFocusChanged(focused, direction, previouslyFocusedRect)
        updateFocusState(focused, true)
    }

    /**
     * 选中状态改变时调用，同步更新焦点状态。
     *
     * @param selected 是否选中
     */
    override fun setSelected(selected: Boolean) {
        super.setSelected(selected)
        updateFocusState(selected, true)
    }

    /**
     * 更新焦点状态，控制背景、缩放、文本显示和通知文本的选中状态。
     *
     * @param focused 是否聚焦
     * @param withAnimation 是否使用动画
     */
    private fun updateFocusState(focused: Boolean, withAnimation: Boolean) {
        // 设置通知文本的选中状态
        binding.tvNotification.isSelected = focused
        binding.rlBg.isSelected = focused

        if (withAnimation) {
            // 使用动画更新状态
            animateBackgroundColor(focused)
            //animateIconScale(focused)
            animateBackgroundScale(focused)
            animateTextVisibility(focused)
        } else {
            // 直接更新状态，无动画
            backgroundDrawable?.setColor(if (focused) focusColor else normalColor)
            //binding.tvNotification.scaleX = if (focused) scaleFactor else 1f
            //binding.tvNotification.scaleY = if (focused) scaleFactor else 1f
            binding.rlBg.scaleX = if (focused) scaleFactor else 1f
            binding.rlBg.scaleY = if (focused) scaleFactor else 1f
            binding.focusText.apply {
                alpha = if (focused) 1.0f else 0.0f
                visibility = if (focused) VISIBLE else INVISIBLE
            }
        }
    }

    /**
     * 动画更新背景颜色，从起始颜色渐变到目标颜色。
     *
     * @param focused 是否聚焦
     */
    private fun animateBackgroundColor(focused: Boolean) {
        val startColor = if (focused) normalColor else focusColor
        val endColor = if (focused) focusColor else normalColor
        ValueAnimator.ofObject(ArgbEvaluator(), startColor, endColor).apply {
            duration = animationDuration
            addUpdateListener { animator ->
                backgroundDrawable?.setColor(animator.animatedValue as Int)
            }
            start()
        }
    }

    /**
     * 动画更新通知文本的缩放比例。
     *
     * @param focused 是否聚焦
     */
    private fun animateIconScale(focused: Boolean) {
        val scale = if (focused) scaleFactor else 1f
        binding.tvNotification.animate()
            .scaleX(scale)
            .scaleY(scale)
            .setDuration(animationDuration)
            .setInterpolator(interpolator)
            .start()
    }

    /**
     * 动画更新背景的缩放比例。
     *
     * @param focused 是否聚焦
     */
    private fun animateBackgroundScale(focused: Boolean) {
        val scale = if (focused) scaleFactor else 1f
        binding.rlBg.animate()
            .scaleX(scale)
            .scaleY(scale)
            .setDuration(animationDuration)
            .setInterpolator(interpolator)
            .start()
    }

    /**
     * 动画更新文本的透明度和可见性。
     *
     * @param focused 是否聚焦
     */
    private fun animateTextVisibility(focused: Boolean) {
        val targetAlpha = if (focused) 1.0f else 0.0f
        binding.focusText.animate()
            .alpha(targetAlpha)
            .setDuration(animationDuration)
            .setInterpolator(interpolator)
            .withStartAction {
                if (focused) binding.focusText.visibility = VISIBLE
            }
            .withEndAction {
                if (!focused) binding.focusText.visibility = INVISIBLE
            }
            .start()
    }

    /**
     * 设置聚焦时的背景颜色。
     *
     * @param color 颜色值
     */
    fun setFocusColor(color: Int) {
        focusColor = color
        if (isFocused) {
            backgroundDrawable?.setColor(focusColor)
            invalidate()
        }
    }

    /**
     * 设置非聚焦时的背景颜色。
     *
     * @param color 颜色值
     */
    fun setNormalColor(color: Int) {
        normalColor = color
        if (!isFocused) {
            backgroundDrawable?.setColor(normalColor)
            invalidate()
        }
    }

    /**
     * 设置聚焦时的缩放比例。
     *
     * @param factor 缩放比例（不得小于 1.0）
     */
    fun setScaleFactor(factor: Float) {
        scaleFactor = factor.coerceAtLeast(1.0f)
        if (isFocused) {
            binding.tvNotification.animate()
                .scaleX(scaleFactor)
                .scaleY(scaleFactor)
                .setDuration(animationDuration)
                .setInterpolator(interpolator)
                .start()
            binding.rlBg.animate()
                .scaleX(scaleFactor)
                .scaleY(scaleFactor)
                .setDuration(animationDuration)
                .setInterpolator(interpolator)
                .start()
        }
    }

    /**
     * 设置动画持续时间。
     *
     * @param duration 持续时间（毫秒，不得为负）
     */
    fun setAnimationDuration(duration: Long) {
        animationDuration = duration.coerceAtLeast(0)
    }

    /**
     * 设置动画插值器。
     *
     * @param customInterpolator 自定义插值器
     */
    fun setInterpolator(customInterpolator: DecelerateInterpolator) {
        interpolator = customInterpolator
    }

    /**
     * 设置聚焦时的文本内容。
     *
     * @param text 文本内容
     */
    fun setFocusTextContent(text: String) {
        focusTextContent = text
        binding.focusText.text = text
    }

    /**
     * 设置聚焦文本的大小。
     *
     * @param size 文本大小（sp）
     */
    fun setFocusTextSize(size: Float) {
        focusTextSize = size
        binding.focusText.textSize = size
    }

    /**
     * 设置聚焦文本的颜色。
     *
     * @param color 颜色值
     */
    fun setFocusTextColor(color: Int) {
        focusTextColor = color
        binding.focusText.setTextColor(color)
    }

    /**
     * 设置通知文本的内容。
     *
     * @param text 通知文本内容
     */
    fun setNotificationText(text: String) {
        binding.tvNotification.text = text
    }
}